using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace HslControls.Charts
{
	/// <summary>
	/// 数据串基类，该类为抽象类，无法实例化。
	/// </summary>
	[TypeConverter(typeof(ExpandableObjectConverter))]
	public abstract class SeriesBase
	{
		private HslChart _chart;

		private string _title = "Series";

		private ChartPointCollection _points = new ChartPointCollection();

		private int _scalesXAt = 0;

		private int _scalesYAt = 0;

		private Color _color = Color.FromArgb(232, 17, 35);

		private bool _visible = true;

		private Label _legend;

		private bool _legendVisible = true;

		/// <summary>
		/// 图表对象
		/// </summary>
		[Browsable(false)]
		public HslChart Chart
		{
			get
			{
				return _chart;
			}
			internal set
			{
				_chart = value;
			}
		}

		/// <summary>
		/// 标题
		/// </summary>
		[Category("HslChart")]
		[Description("标题。")]
		[DefaultValue("Series")]
		public string Title
		{
			get
			{
				return _title;
			}
			set
			{
				_title = value;
				_legend.Text = _title;
			}
		}

		/// <summary>
		/// 数据点
		/// </summary>
		[Category("HslChart")]
		[Description("数据点。")]
		[TypeConverter(typeof(CollectionConverter))]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		public ChartPointCollection Points
		{
			get
			{
				return _points;
			}
			private set
			{
				_points = value;
			}
		}

		/// <summary>
		/// 数据点集合中数据值X的最大值
		/// </summary>
		[Browsable(false)]
		public double? MaxValueX
		{
			get
			{
				if (_points == null || _points.Count < 1)
				{
					return null;
				}
				IEnumerable<double> lstX = _points.Select((ChartPoint cp) => cp.X);
				return lstX.Max();
			}
		}

		/// <summary>
		/// 数据点集合中数据值X的最小值
		/// </summary>
		[Browsable(false)]
		public double? MinValueX
		{
			get
			{
				if (_points == null || _points.Count < 1)
				{
					return null;
				}
				IEnumerable<double> lstX = _points.Select((ChartPoint cp) => cp.X);
				return lstX.Min();
			}
		}

		/// <summary>
		/// 数据点集合中数据值Y的最大值
		/// </summary>
		[Browsable(false)]
		public double? MaxValueY
		{
			get
			{
				if (_points == null || _points.Count < 1)
				{
					return null;
				}
				IEnumerable<double> lstY = _points.Select((ChartPoint cp) => cp.Y);
				return lstY.Max();
			}
		}

		/// <summary>
		/// 数据点集合中数据值Y的最小值
		/// </summary>
		[Browsable(false)]
		public double? MinValueY
		{
			get
			{
				if (_points == null || _points.Count < 1)
				{
					return null;
				}
				IEnumerable<double> lstY = _points.Select((ChartPoint cp) => cp.Y);
				return lstY.Min();
			}
		}

		/// <summary>
		/// 附着的X轴序号
		/// </summary>
		[Category("HslChart")]
		[Description("附着的X轴序号。")]
		[DefaultValue(0)]
		public int ScalesXAt
		{
			get
			{
				return _scalesXAt;
			}
			set
			{
				if (value < 0)
				{
					_scalesXAt = 0;
				}
				else
				{
					_scalesXAt = value;
				}
			}
		}

		/// <summary>
		/// 附着的X轴
		/// </summary>
		[Browsable(false)]
		public Axis ParentAxisX
		{
			get
			{
				if (_chart != null && _scalesXAt < _chart.AxisX.Count)
				{
					return _chart.AxisX[_scalesXAt];
				}
				return null;
			}
		}

		/// <summary>
		/// 附着的Y轴序号
		/// </summary>
		[Category("HslChart")]
		[Description("附着的Y轴序号。")]
		[DefaultValue(0)]
		public int ScalesYAt
		{
			get
			{
				return _scalesYAt;
			}
			set
			{
				if (value < 0)
				{
					_scalesYAt = 0;
				}
				else
				{
					_scalesYAt = value;
				}
			}
		}

		/// <summary>
		/// 附着的Y轴
		/// </summary>
		[Browsable(false)]
		public Axis ParentAxisY
		{
			get
			{
				if (_chart != null && _scalesYAt < _chart.AxisY.Count)
				{
					return _chart.AxisY[_scalesYAt];
				}
				return null;
			}
		}

		/// <summary>
		/// 颜色
		/// </summary>
		[Category("HslChart")]
		[Description("颜色。")]
		public Color Color
		{
			get
			{
				return _color;
			}
			set
			{
				_color = value;
			}
		}

		/// <summary>
		/// 显示/隐藏
		/// </summary>
		[Category("HslChart")]
		[Description("显示/隐藏。")]
		[DefaultValue(true)]
		public bool Visible
		{
			get
			{
				return _visible;
			}
			set
			{
				_visible = value;
			}
		}

		/// <summary>
		/// 图例
		/// </summary>
		[Browsable(false)]
		internal Label Legend
		{
			get
			{
				return _legend;
			}
			set
			{
				_legend = value;
			}
		}

		/// <summary>
		/// 显示/隐藏图例
		/// </summary>
		[Category("HslChart")]
		[Description("显示/隐藏图例。")]
		[DefaultValue(true)]
		public bool LegendVisible
		{
			get
			{
				return _legendVisible;
			}
			set
			{
				_legendVisible = value;
				_legend.Visible = _legendVisible;
			}
		}

		/// <summary>
		/// 构造函数
		/// </summary>
		public SeriesBase()
		{
			_color = GetColorByIndex(HslChart.ColorIndex);
			HslChart.ColorIndex++;
			_legend = new Label
			{
				AutoSize = true,
				Padding = new Padding(12, 0, 0, 0),
				Text = Title
			};
			_legend.Paint += PaintLegend;
		}

		/// <summary>
		/// 获取颜色
		/// </summary>
		/// <param name="index">序号</param>
		/// <returns>颜色</returns>
		public static Color GetColorByIndex(int index)
		{
			return HslChart.Colors[index - HslChart.Colors.Count * (index / HslChart.Colors.Count)];
		}

		/// <summary>
		/// 计算数据点与图表左边缘的距离
		/// </summary>
		/// <param name="xValue">数据值X</param>
		/// <returns>距离</returns>
		public float CountLeft(double xValue)
		{
			double axisXLenght = _chart.Border.Width;
			double unitX = axisXLenght / ParentAxisX.Range;
			double x = (xValue - ParentAxisX.MinValue) * unitX;
			if (ParentAxisX.IsReverse)
			{
				x = axisXLenght - x;
			}
			x += (double)_chart.Border.Left;
			return Convert.ToSingle(x);
		}

		/// <summary>
		/// 计算数据点与图表上边缘的距离
		/// </summary>
		/// <param name="yValue">数据值Y</param>
		/// <returns>距离</returns>
		public float CountTop(double yValue)
		{
			double axisYLenght = _chart.Border.Height;
			double unitY = axisYLenght / ParentAxisY.Range;
			double y = (yValue - ParentAxisY.MinValue) * unitY;
			if (!ParentAxisY.IsReverse)
			{
				y = axisYLenght - y;
			}
			y += (double)_chart.Border.Top;
			return Convert.ToSingle(y);
		}

		/// <summary>
		/// 获取数据点在图表上的坐标数组
		/// </summary>
		/// <returns>坐标数组</returns>
		public PointF[] GetLocationArray()
		{
			if (_points != null || _points.Count > 0)
			{
				PointF[] pts = new PointF[_points.Count];
				for (int i = 0; i < pts.Length; i++)
				{
					pts[i] = new PointF(_points[i].Left, _points[i].Top);
				}
				return pts;
			}
			return null;
		}

		/// <summary>
		/// 设置数据值Y
		/// </summary>
		/// <param name="values">数据值数组</param>
		/// <param name="startValue">数据值X的起始值</param>
		/// <param name="valueStep">数据值X的步长</param>
		public void SetValuesY(double[] values, double startValue = 0.0, double valueStep = 0.1)
		{
			_points.Clear();
			if (values != null && values.Length != 0)
			{
				_chart.BeginUpdate();
				for (int i = 0; i < values.Length; i++)
				{
					_points.Add(new ChartPoint((double)i * valueStep + startValue, values[i]));
				}
				_chart.EndUpdate();
			}
		}

		/// <summary>
		/// 设置数据值X
		/// </summary>
		/// <param name="values">数据值数组</param>
		/// <param name="startValue">数据值Y的起始值</param>
		/// <param name="valueStep">数据值X的步长</param>
		public void SetValuesX(double[] values, double startValue = 0.0, double valueStep = 0.1)
		{
			_points.Clear();
			if (values != null && values.Length != 0)
			{
				_chart.BeginUpdate();
				for (int i = 0; i < values.Length; i++)
				{
					_points.Add(new ChartPoint(values[i], (double)i * valueStep + startValue));
				}
				_chart.EndUpdate();
			}
		}

		/// <summary>
		/// 通过横坐标查找<see cref="T:HslControls.Charts.ChartPoint" />对象数组
		/// </summary>
		/// <param name="x">横坐标</param>
		/// <param name="range">范围</param>
		/// <returns><see cref="T:HslControls.Charts.ChartPoint" />对象数组</returns>
		public ChartPoint[] SelectAllByX(int x, float range = 0f)
		{
			return _points.Where((ChartPoint cp) => (float)cp.Left >= (float)x - range && (float)cp.Left <= (float)x + range)?.ToArray();
		}

		/// <summary>
		/// 通过横坐标查找<see cref="T:HslControls.Charts.ChartPoint" />对象
		/// </summary>
		/// <param name="x">横坐标</param>
		/// <param name="range">范围</param>
		/// <returns><see cref="T:HslControls.Charts.ChartPoint" />对象</returns>
		public ChartPoint SelectByX(int x, float range = 0f)
		{
			ChartPoint[] array = SelectAllByX(x, range);
			if (array == null)
			{
				return null;
			}
			int minX = int.MaxValue;
			ChartPoint bestCP = null;
			ChartPoint[] array2 = array;
			foreach (ChartPoint cp in array2)
			{
				int dVal = Math.Abs(x - cp.Left);
				if (dVal < minX)
				{
					bestCP = cp;
					minX = dVal;
				}
			}
			return bestCP;
		}

		/// <summary>
		/// 通过纵坐标查找<see cref="T:HslControls.Charts.ChartPoint" />对象数组
		/// </summary>
		/// <param name="y">纵坐标</param>
		/// <param name="range"></param>
		/// <returns><see cref="T:HslControls.Charts.ChartPoint" />对象数组</returns>
		public ChartPoint[] SelectAllByY(int y, float range = 0f)
		{
			return _points.Where((ChartPoint cp) => (float)cp.Top >= (float)y - range && (float)cp.Top <= (float)y + range)?.ToArray();
		}

		/// <summary>
		/// 通过纵坐标查找<see cref="T:HslControls.Charts.ChartPoint" />对象
		/// </summary>
		/// <param name="y">纵坐标</param>
		/// <param name="range"></param>
		/// <returns><see cref="T:HslControls.Charts.ChartPoint" />对象</returns>
		public ChartPoint SelectByY(int y, float range = 0f)
		{
			ChartPoint[] array = SelectAllByY(y, range);
			if (array == null)
			{
				return null;
			}
			int minY = int.MaxValue;
			ChartPoint bestCP = null;
			ChartPoint[] array2 = array;
			foreach (ChartPoint cp in array2)
			{
				int dVal = Math.Abs(y - cp.Top);
				if (dVal < minY)
				{
					bestCP = cp;
					minY = dVal;
				}
			}
			return bestCP;
		}

		/// <summary>
		/// 通过横纵坐标查找<see cref="T:HslControls.Charts.ChartPoint" />对象数组
		/// </summary>
		/// <param name="x">横坐标</param>
		/// <param name="y">纵坐标</param>
		/// <param name="range">范围</param>
		/// <returns><see cref="T:HslControls.Charts.ChartPoint" />对象数组</returns>
		public ChartPoint[] SelectAll(int x, int y, float range = 0f)
		{
			return _points.Where((ChartPoint cp) => (float)cp.Left >= (float)x - range && (float)cp.Left <= (float)x + range && (float)cp.Top >= (float)y - range && (float)cp.Top <= (float)y + range)?.ToArray();
		}

		/// <summary>
		/// 通过横纵坐标查找<see cref="T:HslControls.Charts.ChartPoint" />对象
		/// </summary>
		/// <param name="x">横坐标</param>
		/// <param name="y">纵坐标</param>
		/// <param name="range">范围</param>
		/// <returns><see cref="T:HslControls.Charts.ChartPoint" />对象</returns>
		public ChartPoint Select(int x, int y, float range = 0f)
		{
			ChartPoint[] array = SelectAll(x, y, range);
			if (array == null)
			{
				return null;
			}
			int min = int.MaxValue;
			ChartPoint bestCP = null;
			ChartPoint[] array2 = array;
			foreach (ChartPoint cp in array2)
			{
				int dVal = Math.Abs(x - cp.Left) + Math.Abs(y - cp.Top);
				if (dVal < min)
				{
					bestCP = cp;
					min = dVal;
				}
			}
			return bestCP;
		}

		/// <summary>
		/// 绘制数据
		/// </summary>
		/// <param name="g">绘图对象</param>
		internal virtual void Draw(Graphics g)
		{
		}

		/// <summary>
		/// 图例重绘方法，用于绘制图标。
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected virtual void PaintLegend(object sender, PaintEventArgs e)
		{
		}
	}
}
